package com.zkh.myutils.extension.image;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;

import javax.imageio.ImageIO;

import com.swetake.util.Qrcode;
import com.zkh.myutils.code.Charsets;
import com.zkh.myutils.utils.UtilsException;

/**
 * 二维码生成工具类
 * @author zkh
 */
public class QRcode {
	
	/******  二维码版本  *******/
	private int version = 9;
	
	/******  二维码颜色  *******/
	private Color bgColor = Color.WHITE;
	private Color fgColor = Color.BLACK;
	private BufferedImage logoImage = null;
	
	/**
	 * 设置二维码背景色，默认为白色
	 * @param bgColor 背景色
	 */
	public void setBgColor(Color bgColor) {
		this.bgColor = bgColor;
	}
	/**
	 * 设置二维码前景色，默认为黑色
	 * @param fgColor 前景色
	 */
	public void setFgColor(Color fgColor) {
		this.fgColor = fgColor;
	}
	
	/**
	 * 无参构造
	 */
	public QRcode(){}

	/**
	 * 构造方法
	 * @param version 二维码版本，取值范围1-40，值越大尺寸越大，可存储的信息越大。默认版本为9
	 */
	public QRcode(int version){
		//范围
		if(version<1 || version>40) {
			throw new UtilsException("二维码版本区间应为[1, 40]");
		}
		this.version = version;
	}
	
	/**
	 * 输出二维码
	 * @param bi 生成的二维码流
	 * @param outputStream 输出流
	 */
	public void output(BufferedImage bi, OutputStream outputStream){
		try {
			ImageIO.write(bi, "png", outputStream);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * 生成带logo的二维码
	 * @param content 二维码保存内容
	 * @param logoPath logo路径
	 */
	public BufferedImage create(String content, String logoPath){
		//File对象
		File file = new File(logoPath);
		//存在
		if(file.exists()){
			try {
				logoImage = ImageIO.read(file);
			} catch (IOException e) {
				throw new RuntimeException();
			}
		}
		return create(content);
	}
	
	/**
	 * 生成带logo的二维码
	 * @param content 二维码保存内容
	 * @param logoImage 图片资源
	 */
	public BufferedImage create(String content, BufferedImage logoImage){
		this.logoImage = logoImage;
		return create(content);
	}
	
	/**
	 * 生成二维码
	 * @param content 需要存储在二维码中的文本
	 */
	public BufferedImage create(String content){
		try {
			//实例化二维码对象
			Qrcode qrcode = new Qrcode();
			//设置二维码排错率，可选L(7%)、M(15%)、Q(25%)、H(30%)，排错率越高可存储的信息越少，但对二维码清晰度的要求越小
			qrcode.setQrcodeErrorCorrect('H');
			//N代表数字,A代表字符a-Z,B代表其他字符
			qrcode.setQrcodeEncodeMode('B');
			//设置二维码版本，取值范围1-40，值越大尺寸越大，可存储的信息越大9
			qrcode.setQrcodeVersion(version);
			//二维码内容
			byte[] contentBytes = content.getBytes(Charsets.UTF_8);// 设置编码格式为UTF-8
			//解析长度
			boolean[][] codeOut = qrcode.calQrcode(contentBytes);
			int len = codeOut.length;
			//判断内容是否超长
			if(contentBytes.length>len) {
				throw new RuntimeException("content.getBytes(\"utf-8\").length的值不能超过" + len);
			}
			//二维码宽度（+4是为了留出边框）
			int width = len * 3 + 4, height = width;
			//实例化图片
			BufferedImage bufImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
			//获取Graphics2D对象
			Graphics2D gs = bufImg.createGraphics();
			//设置背景色为白色
			gs.setBackground(bgColor); 
			gs.clearRect(0, 0, width, height);
			//设定图像颜色 为黑色
			gs.setColor(fgColor);
			//设置偏移量 不设置可能导致解析出错
			int pixoff = 2; 
			// 输出内容 --> 二维码
			for (int i = 0; i < len; i++) {
				for (int j = 0; j < len; j++) {
					if (codeOut[j][i]) {
						gs.fillRect(j * 3 + pixoff, i * 3 + pixoff, 3, 3);
					}
				}
			}
			//如果图片存在，则将图片写入到二维码中
			if(logoImage!=null){
				//获取logo的大小
				int twidth = logoImage.getWidth();
				int theight = logoImage.getHeight();
				//如果logo图片的宽高大于二维码宽高的2/3，则抛出异常
				if(theight>height*0.67 || twidth>width*0.67){
					throw new RuntimeException("logo图片的宽高太大");
				}
				//计算logo距离二维码上端和左端的大小
				int top = (height-theight)/2;
				int left = (width-twidth)/2;
				//将图片写入到二维码中
				gs.drawImage(logoImage, left, top, twidth, theight, null);
				gs.dispose();
			}
			//刷新
			bufImg.flush();
			//返回图片对象
			return bufImg;

		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

}